/*
 * Threadpool.h
 *
 *  Created on: 2022年9月12日
 *      Author: wocao
 */
#include <unordered_map>
#include <pthread.h>
#include <unistd.h>
#include <iostream>
#include "../thread/AbstractThread.h"
#include "../thread/AbstractThreadFactory.h"
using namespace std;

#ifndef POOL_THREADPOOL_H_
#define POOL_THREADPOOL_H_
class Threadpool {
public:
	Threadpool(int num, void* (*start)(void*), void *arg); //num：池中的线程数量 start：函数指针 arg：start指向的函数的参数
	Threadpool(int num, void *classaddr, void* (*start)(void*), void *arg); //num：池中的线程数量  classaddr：start指向函数所在类的指针 start：函数指针 arg：start指向的函数的参数
	~Threadpool();
	void init(int num, void *classaddr, void* (*start)(void*), void *arg); //根據構造函數參數進行初始化
	void getThread(void *arg); //從池中取出一個線程並執行線程
	inline int allThreadNum(); //獲取池中所有線程的個數
	inline int emptyThreadNum(); //獲取池中空閒線程的數量
	inline int getUsedThreadNum(); //獲取池中已使用線程的數量
	inline void setThreadnum(int threadnum); //設置池中清理線程清理後剩餘的線程數量（當獲取線程阻塞狀態爲true時空餘線程數量爲0則增加線程；獲取線程阻塞狀態爲false時空餘線程數量爲0則阻塞等待其他線程執行完畢時獲取線程執行）
	void expansioncap(int exp); //增加exp個線程到池中
	inline void setExpansioncapable(bool expansioncapable);//設置獲取線程阻塞狀態
	inline void setExpansion(int expansion); //設置expansion值的大小
	void exitThread(pthread_t pt); //線程運行結束後調用的方法，將自己從usedmap中刪除並加入到resivectormap中
private:
	void addThread(int num, void* (*start)(void*), void *arg);//往池中加入num個線程
	void addThread(int num, void *classaddr, void* (*start)(void*), void *arg);//往池中加入num個線程
	void cleanThread();//創建線程池對象時會創建一個清理線程，用將線程數量保持在threadnum個。（獲取線程阻塞狀態爲false時不開啓此線程）
	unordered_map<pthread_t, AbstractThread*> usedmap;//已用線程的哈希表
	unordered_map<pthread_t, AbstractThread*> resivectormap;//空餘線程的哈希表
	volatile int resithread = 0;//空餘線程的數量
	volatile int usedthread = 0;//已用線程的數量
	int allthread = 0;//全部線程的數量
	int expansion = 8;//當設置爲獲取線程非阻塞狀態時每次加入線程的數量
	int threadnum = 0;//池中默認的空餘線程數量
	pthread_spinlock_t spin_get_thread;//操作usedmap和resivectormap的自旋鎖
	pthread_mutex_t mutex_done_thread;//當設置爲獲取線程阻塞狀態時用於傳達互斥量喚醒信號的鎖
	pthread_spinlock_t spin_resithread;//操作resithread的自旋鎖
	pthread_spinlock_t spin_usedthread;//操作usedthread的自旋鎖
	pthread_spinlock_t spin_all_thread;//操作allthread的自旋鎖
	pthread_cond_t cond;//當設置爲獲取線程阻塞狀態時的互斥量
	void* (*start)(void*) = NULL;//函数指针
	void *arg = NULL;//start指向的函数的参数
	void *classaddr = NULL;//start指向函数所在类的指针
	bool expansioncapable = true;//設置是否爲獲取線程阻塞狀態（當空餘線程數量爲0時是否增加線程，true爲增加；false爲不增加，當空餘線程數量爲0時阻塞等待其他線程執行完畢時獲取線程執行）
	bool thread11 = false;//創建的線程是否爲C++11標準
	bool done = true;//獲取線程阻塞狀態時互斥量的輔助變量
};
void Threadpool::setExpansion(int expansion) {
	this->expansion = expansion;
}

int Threadpool::allThreadNum() {
	pthread_spin_lock(&spin_all_thread);
	int a = this->allthread;
	pthread_spin_unlock(&spin_all_thread);
	return a;
}

int Threadpool::emptyThreadNum() {
	pthread_spin_lock(&spin_resithread);
	int a = this->resithread;
	pthread_spin_unlock(&spin_resithread);
	return a;
}

int Threadpool::getUsedThreadNum() {
	pthread_spin_lock(&spin_usedthread);
	int a = this->usedthread;
	pthread_spin_unlock(&spin_usedthread);
	return a;
}

void Threadpool::setThreadnum(int threadnum) {
	this->threadnum = threadnum;
}

void Threadpool::setExpansioncapable(bool expansioncapable){
	this->expansioncapable = expansioncapable;
}

#endif /* POOL_THREADPOOL_H_ */
